﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.WorkFlow.Domain;
using Windows.Infrastructure.Share.Extensions;
using Windows.Infrastructure.Share.Security;
using Windows.WorkFlow.Infrastructure.EFCore;
using Windows.WorkFlow.Domain.Enums;
using System.Xml.Linq;
using Windows.Infrastructure.EFCore.Share.Extensions;

namespace Windows.WorkFlow.Service
{
    public class WorkFlowManager : IWorkFlowManager
    {
        private readonly WorkFlowDbContext _db;
        private readonly ICurrentUser _currentUser;
        public WorkFlowManager(WorkFlowDbContext db, ICurrentUser currentUser)
        {
            _db = db;
            _currentUser = currentUser;
        }
        /// <summary>
        /// 开始任务
        /// </summary>
        /// <param name="runtime"></param>
        /// <returns></returns>
        public async System.Threading.Tasks.Task Start(FlowRuntime runtime)
        {
            Execution execution = new()
            {
                FlowInstanceId = runtime.FlowInstanceId,
                NodeId = runtime.CurrentNode.Id,
                NodeName = runtime.CurrentNode.Properties.Text,
                NodeType = runtime.CurrentNode.Type,
                EndOn = DateTime.Now,
            };
            Domain.Task task = new()
            {
                NodeId = runtime.CurrentNode.Id,
                NodeName = runtime.CurrentNode.Properties.Text,
                AssigneeId = _currentUser.EmployeeId,
                AssigneeName = _currentUser.Name,
                Status = TaskStatusEnum.Pass.ToInt(),
                Comment = $"开始了{runtime.FlowName}",
                EndOn = DateTime.Now,
            };
            execution.Tasks.Add(task);
            await Next(runtime);
        }
        /// <summary>
        /// 下一步
        /// </summary>
        /// <param name="runtime"></param>
        /// <returns></returns>
        public async System.Threading.Tasks.Task Next(FlowRuntime runtime)
        {
            foreach (var edges in runtime.ToNodeEdges.Values)
            {
                foreach (var edge in edges)
                {
                    var node = runtime.GetNextNode(edge.SourceNodeId);
                    Execution e = new()
                    {
                        FlowInstanceId = runtime.FlowInstanceId,
                        NodeId = node.Id,
                        NodeName = node.Properties!.Text,
                        NodeType = node.Type,
                    };
                    if (e.NodeType == FlowNodeTypeEnum.ParallelGateway.ToString())
                    {
                        ParallelGateway(runtime, e);
                    }
                    else if (e.NodeType == FlowNodeTypeEnum.UserTask.ToString())
                    {
                        UserTask(runtime, e);
                    }
                    else if (e.NodeType == FlowNodeTypeEnum.EndEvent.ToString())
                    {
                        EndEvent(runtime,e);
                    }
                    _db.Execution.Add(e);
                }
            }
            await _db.SaveChangesAsync();
        }
        /// <summary>
        /// 并行网关节点
        /// </summary>
        /// <param name="runtime"></param>
        /// <param name="e"></param>
        private void ParallelGateway(FlowRuntime runtime, Execution e)
        {
            var parallelEdges = runtime.Edges.Where(x => x.TargetNodeId == e.NodeId).ToList();
            foreach (var item in parallelEdges)
            {
                var node1 = runtime.Nodes[item.TargetNodeId];
                Execution e1 = new()
                {
                    FlowInstanceId = runtime.FlowInstanceId,
                    NodeId = node1.Id,
                    NodeName = node1.Properties!.Text,
                    NodeType = node1.Type,
                };
                _db.Execution.Add(e1);
                Domain.Task task1 = new()
                {
                    NodeId = node1.Id,
                    NodeName = node1.Properties.Text,
                    Status = TaskStatusEnum.Processing.ToInt(),
                };
                e.Tasks.Add(task1);
            }
        }
        /// <summary>
        /// 用户任务节点
        /// </summary>
        /// <param name="runtime"></param>
        /// <param name="e"></param>
        private void UserTask(FlowRuntime runtime, Execution e)
        {
            Domain.Task task = new()
            {
                NodeId = e.NodeId,
                NodeName = e.NodeName,
                Status = TaskStatusEnum.Processing.ToInt(),
            };
            e.Tasks.Add(task);
        }
        /// <summary>
        /// 结束节点
        /// </summary>
        /// <param name="runtime"></param>
        /// <param name="e"></param>
        private void EndEvent(FlowRuntime runtime, Execution e)
        {
            e.EndOn = DateTime.Now;
            Domain.Task task = new()
            {
                NodeId = e.NodeId,
                NodeName = e.NodeName,
                Status = TaskStatusEnum.Pass.ToInt(),
                Comment = $"{runtime.FlowName}结束",
                EndOn = e.EndOn
            };
            e.Tasks.Add(task);
        }
    }
}
